Wesbos - 로컬스토리지 & 이벤트 위임


완성본 예시

로컬스토리지의 활용법과 이벤트 위임이라는 굉장히 유용한 기능을 배울 수 있는 챕터였다. (어려웠지만….. ㅋㅋ)

물론 mongoDB와 같은 DB를 사용하면 크게 사용할 일은 없겠지만, 간단한 웹서비스 등을 만들 때에는 유용할 것 같다.


로직

  1. 사용할 객체들 변수화 하기 (const) + 이벤트리스너와 함수 생성
  2. <input>에입력한 값을 인식할 수 있도록 함수 설정
  3. add item(submit)을 누르면
  4. 가 append!
  5. append된 요소들이 로컬스토리지에 저장 되도록 설정
  6. 체크박스의 체크 유무 또한 로컬 스토리지에 저장 되도록 설정 (위임도 필요)
  7. 삭제 기능 추가

const 선언

💡 Add item버튼, html에 추가될 아이템 ul, 아이템 배열을 생성하여 변수화해준다.

1
2
3
const addItems = document.querySelector('.add-items');
const itemsList = document.querySelector('.plates');
const items = [];

addEventListener

1
2
3
4
5
6
7
function addItem(e) {
e.preventDefault();
//잘 작동하는지 확인!
console.log('hi');
}

addItems.addEventListener('submit', addItem);

event.preventDefault()

💡 페이지의 이동 또는 리로드가 실행되지 않도록 막아준다!

⇒ 이 챕터에선 submit을 눌러도 페이지가 새로고침되지 않고 submit만 될 수 있도록 하기 위해 사용


<input>에 입력한 텍스트 인식

💡 <input> 에 입력한 값이 잘 불러와질 수 있도록 addItem 함수를 수정보완

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function addItem(e) {
e.preventDefault();
// 입력된 값을 text로 변수화
text = this.querySelector('[name=item]').value;
// 객체 생성
item = {
text: text,
done: false,
};
//찍어보기
console.log(item);

// 미리 생성한 배열인 items에 item을 push
}

출력 예시


미리 생성한 배열인 items에 item을 push!

1
2
3
4
5
6
7
8
9
function addItem(e) {
e.preventDefault();
text = this.querySelector('[name=item]').value;
const item = {
text: text,
done: false,
};
items.push(item);
}

setItem()

💡 로컬스토리지 객체에 접근하여 항목 하나를 추가한다

⭐️JSON.stringify()⭐️

💡 JavaScript값이나 객체를 JSON형태의 문자열로 변환한다.

(배열 자체가 문자열이 되어 반환된다고 생각하면 편할듯?)

1
2
console.log(JSON.stringify({ x: 5, y: 6 }));
// 예상 결과값 : "{"x":5,"y":6}"

버튼 누르면 → 아이템(<li>) append!

💡 우선 appendList라는 함수를 생성해주자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function appendList(plates = [], platesList) {
platesList.innerHTML = plates
.map((plate, i) => {
return `
<li>
<input type="checkbox" data-index=${i} id="item${i}" ${
plate.done ? 'checked' : ''
} />
<label for="item${i}">${plate.text}</label>
</li>
`;
})
.join(''); // map에 의해서 콤마(,)가 append될 때마다 붙기 때문에 이를 제거하기 위해 join을 사용!
}

join('')을 작성하지 않으면 이렇게 된다...


localStorage

getItem()

💡 로컬스토리지 내에서 항목을 읽어냄

⭐️JSON.parse()⭐️

💡 문자열로 구성된 JSON을 JavaScript값이나 객체로 반환한다.

문자열 → JavaScript 객체

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 로컬 스토리지에 저장된 메뉴가 있으면 불러오고, 없으면 빈 배열!
const items = JSON.parse(localStorage.getItem('items')) || [];

function addItem(e) {
e.preventDefault();
// input박스에 입력될 텍스트를 변수화
const text = this.querySelector('[name=item]').value;
const item = {
text: text,
// 체크박스에 활용할 Boolean값
done: false,
};

items.push(item);
populateList(items, itemsList);
localStorage.setItem('items', JSON.stringify(items));
this.reset();
}

체크 유무 저장

💡 위의 items 객체에서 설정한 done의 boolean값을 저장하여
체크박스의 체크 유무를 새로고침해도 유지될 수 있도록 설정

1
2
3
4
5
6
7
8
function toggleDone(e) {
if (!e.target.matches('input')) return; // input 태그가 아니면 종료 (label도 찍힐 수 있기 때문)
const el = e.target;
const index = el.dataset.index;
items[index].done = !items[index].done; // 반대값 설정 트릭 !
localStorage.setItem('items', JSON.stringify(items));
appendList(items, itemsList);
}

삭제기능 추가

💡 wrapper 하단에 Clear All 버튼을 만들어 준 뒤,

localStorage.removeItem() 을 사용해서 삭제기능을 구현하면 된다.

removeItem()

💡 로컬 스토리지에서 항목 하나를 제거한다.

1
2
3
4
5
6
7
8
9
10
11
// 클리어 버튼 변수화
const clear = document.querySelector('.clear');

function removeAll() {
localStorage.removeItem('items');
// removeItem은 로컬스토리지 삭제 기능만 하기 때문에, li가 제거될 수 있도록 새로고침을 해준다.
location.reload();
}

// 클릭 이벤트 & 함수 할당
clear.addEventListener('click', removeAll);

최종 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
const addItems = document.querySelector('.add-items');
const itemsList = document.querySelector('.plates');
const clear = document.querySelector('.clear');
const items = JSON.parse(localStorage.getItem('items')) || [];

function addItem(e) {
e.preventDefault();
text = this.querySelector('[name=item]').value;
const item = {
text: text,
done: false,
};
items.push(item);
appendList(items, itemsList);
localStorage.setItem('items', JSON.stringify(items));
this.reset();
}

// 원본 훼손을 최대한 방지하기 위해 items 복사!
function appendList(plates = [], plateList) {
plateList.innerHTML = plates
.map((plate, i) => {
return `
<li>
<input type="checkbox" data-index=${i} id="items${i}" ${
plate.done ? 'checked' : ''
}/>
<label for="items${i}">${plate.text}</label>
</li>
`;
})
.join('');
}

function toggleDone(e) {
if (!e.target.matches('input')) return; // skip this unless it's an input
const el = e.target;
const index = el.dataset.index;
items[index].done = !items[index].done;
localStorage.setItem('items', JSON.stringify(items));
appendList(items, itemsList);
}

function removeAll() {
localStorage.removeItem('items');
location.reload();
}

clear.addEventListener('click', removeAll);

addItems.addEventListener('submit', addItem);
itemsList.addEventListener('click', toggleDone);

appendList(items, itemsList);

Wesbos - 로컬스토리지 & 이벤트 위임

https://hoonjoo-park.github.io/javascript/wesbos/15. LocalStorage/

Author

Hoonjoo

Posted on

2022-01-04

Updated on

2022-02-07

Licensed under

Comments